
	 //Method to build a path
	 getPath = function (x,y,x1,y1){
       var p ;
       var d;
       
       if (x < x1) d = +10;
       else d = -10;
       
       p= p + " M " + x + "," + y; //Origine

       p= p + " L " + (x + d) +"," + y; //Horizontal line start +10 o -10 depending on EST OVEST

       p= p + " L " + (x1 - d) +"," + y1; //Horizontal line

       p= p + " L " + x1 + "," + y1; //Destination
       return p;

     }               

	 mymoveBox = function (dx,dy,box){

              //Retrieve graphic object that rappresent entity
              var me = box; //TODO Revision 
              
              me.transform('t' + dx + ',' + dy);

              var _Schema = me.ParentSchema;
            
              for(var i=0; i<_Schema.relations.length;i++){ //Loop on relations
                if(_Schema.relations[i].from.name == me.tabName || 
                   _Schema.relations[i].to.name   == me.tabName	
                  ){ //If relation is about FROM or TO Entity
                  console.log("relation " + _Schema.relations[i].name);
                  
                  for(var f=0; f<_Schema.relations[i].relFields.length;f++){ //Loop on relations
                  	
                  	if(_Schema.relations[i].relFields[f].lineRel == null){
                  	}
                  	else{//Only relation line that must by rendered 
                  		
                  	  var fld;
                  	  
                  	  fld = _Schema.relations[i].relFields[f];
                  	  
                  	  //console.log("flgFrom " + flgFrom);
                  	  
                  	  //Retrieve coords matrix 
                  	  pathArray = fld.lineRel.attr("path");

                  	  //Relation line has 4 coords only frist 2 couple need a change
                  	  
                  	  //Retrieve coords of object r 	
                      var BBox;
                      
                      if(_Schema.relations[i].from.name == me.tabName){ 
                        BBox = fld.fieldFrom.r.getBBox();
                      }
                      else{ 
                        BBox = fld.fieldTo.r.getBBox();
                      }
                      
                      //Recalculate coords of relation referring BBox 
                      if(_Schema.relations[i].from.name == me.tabName){
                        //Point 1th
                        pathArray[0][1] = BBox.x + BBox.width;
                        pathArray[0][2] = BBox.y +(BBox.height/2) ; 

                        //Point 2th
                        pathArray[1][1] = BBox.x + BBox.width + 10 ;
                        pathArray[1][2] = BBox.y +(BBox.height/2); 
                      }
                      else{
                        //Point 3th
                        pathArray[2][1] = BBox.x -10;
                        pathArray[2][2] = BBox.y +(BBox.height/2); 

                        //Point 4th
                        pathArray[3][1] = BBox.x ;
                        pathArray[3][2] = BBox.y +(BBox.height/2); 
                      	 
                      }

                      //Update of line that rappresent relation
                      fld.lineRel.attr({path : pathArray});
                      
                    }  
                  }
                }  	                      
              }    	                      

	 }


	Raphael.st.draggable = function() {
	  var me = this,
	      lx = 0,
	      ly = 0,
	      ox = 0,
	      oy = 0,
	      moveFnc = function(dx, dy) {
	          lx = dx + ox;
	          ly = dy + oy;
	          //me.transform('t' + lx + ',' + ly);
              mymoveBox(lx,ly,me);//Continuos movement of relation during drag

	      },
	      startFnc = function() {
	      	console.log("start drag " + me.type+ " " +me.tabName);
	      },
	      endFnc = function() {
	      	  console.log("drop " + me.type+ " " +me.tabName);
	          ox = lx;
	          oy = ly;

              mymoveBox(ox,oy,me);
              
	      };
	  
	  this.drag(moveFnc, startFnc, endFnc);
	};


/*
        //ToolTip 
       this.ToolTip = this.Graph.rect(0,0,100,20)
                  	    .attr({ "fill" : "lightyellow" 
	                           }
	                          );
       this.ToolTip.hide(); 
  */

   //Classe ToolTip
   function ToolTip(Graph,x,y,text) {
   	 this.Graph = Graph; 
   	 this.x = x;
   	 this.y = y;
   	 this.text = text;

     this.render= function (){
     	
       var s = 	this.Graph.set();
     	
       var r = this.Graph.rect(0,0,100,20)
                  	    .attr({ "fill" : "lightyellow" 
	                           }
	                          );
	   s.push(r);                       
	                          
       var t = this.Graph.text(this.x + 1, this.y + (r.getBBox().height / 2), this.text )
	                     .attr({ "font-family" : "Tahoma" 
	                            ,"font-size"   : "10"
	                            ,"text-anchor"   : "start"
	                           }
	                          );

       s.push(t);
       
       var Width =0;
       
       Width = t.getBBox().width + 1 + 1;

       r.attr({ "width" : + Width});	                          
	   
     };

   };
   //Classe DBSchema 
   function DBSchema(name,divName) {
   	 this.name = name;
   	 
	 //TODO Impostare come screen
	 this.Graph = Raphael(divName,"100%", 1000)
	 this.entities = new Array();
	 this.relations = new Array();
	 
	 this.font = "Arial";
     this.fontSize = "20";
     this.hideRelationFieldName ="";

     /*this.setStatusBar= function (txt){
       this.statusBar.attr({ "text" : txt  });
     };*/

     this.getEntityByName= function (tabName){
	   for(var i=0;i<this.entities.length;i++){
	   	 if(this.entities[i].name == tabName)  return	this.entities[i];
	   } 	 
     };
     
     //Factory method of Entity
     this.newEntity= function (schema,tabName,descr,x,y){
       var e = new Entity(schema,tabName,descr);	
     	
       e.Graph = this.Graph;
       e.x = x;
       e.y = y; 	
       e.font = this.font;
       e.fontSize = this.fontSize;
       e.ParentSchema = this; //!!Reference to all Schema to grant access of Relations 
       	
       this.addEntity(e);	
     	
       return e;
     }

	 //Method addEntity
	 this.addEntity = function (entity){
	   this.entities[this.entities.length]=entity;
	   
	   return this;	
     }

     //Factory method of Relation
     this.newRelation= function (name,descr,fromName,toName,x,y){
     	
       var rl = new Relation(name,descr,this.getEntityByName(fromName),this.getEntityByName(toName));	
     	
       rl.Graph = this.Graph;
       rl.x = x;
       rl.y = y; 	
       rl.font = this.font;
       rl.fontSize = this.fontSize;
       rl.hideRelationFieldName	= this.hideRelationFieldName;
        
       this.addRelation(rl);	
     	
       return rl;
     }


	 //Factory method of addRelation
	 this.addRelation = function (relation){
	   this.relations[this.relations.length]=relation;	
     }

	 //Render method
	 this.render = function (){

       //Clear graph 
       this.Graph.clear();

       //Schema title
       this.title = this.Graph.text(this.Graph.width / 2 , 10 , this.name )
	                     .attr({ "font-family" : this.font 
	                            ,"font-size"   : this.fontSize * 2
	                            ,"text-anchor"   : "start"
	                           }
	                          );

       //Status bar
       this.statusBar = this.Graph.text(10 , 200 , "Status bar" )
	                     .attr({ "font-family" : this.font 
	                            ,"font-size"   : this.fontSize * 2
	                            ,"text-anchor"   : "start"
	                           }
	                          );
       
       //Draw Entities and relations
	   for(var i=0;i<this.entities.length;i++)	this.entities[i].render();
	   for(var i=0;i<this.relations.length;i++)	this.relations[i].render();
     }	 
   }

   //Relation Class 
   function RelationField(fieldFrom,fieldTo) {
     this.fieldFrom = fieldFrom;
     this.fieldTo   = fieldTo;
     this.lineRel   = null;
    
	 //Render method
	 this.render = function (){
	   
	   var fromX,fromY,ToX,ToY;
	   
	   if(this.fieldFrom.x < this.fieldTo.x){
         fromX = this.fieldFrom.handlerEstX();
         fromY = this.fieldFrom.handlerEstY();

         ToX = this.fieldTo.handlerOvestX();
         ToY = this.fieldTo.handlerOvestY();

	   }
	   else{
         fromX = this.fieldFrom.handlerOvestX();
         fromY = this.fieldFrom.handlerOvestY();

         ToX = this.fieldTo.handlerEstX();
         ToY = this.fieldTo.handlerEstY();
	   }

	   //Build path 
	   //Valutare di salvare il path almeno per cancellarlo
	   p = getPath(fromX,fromY,ToX,ToY);
	   
	   if(this.hideRelationFieldName!="" && this.fieldFrom.name.indexOf(this.hideRelationFieldName)>0){ //Exclude relation on filed with postfix _UTE
	   }
	   else{
	     //Draw path 
	     var lineRel = this.Graph.path(p);
	   	 this.lineRel = lineRel;

		 //Over
		 lineRel.hover(function () {
		   lineRel.attr("stroke", "red");
		    //r.statusBar.attr({ "text" : r.descr  });
		 }, function () {
		   lineRel.attr("stroke", "black");
		   //r.statusBar.attr({ "text" : ""  });
		 }); 


	   }	   
	 }  
   }
     
   //Relation Class 
   function Relation(name,descr,from,to) {
	 this.name =name;
	 this.descr=descr;
     this.from = from;
     this.to   = to;
	 this.relFields = new Array();
     this.Graph = null;     
     this.hideRelationFieldName = "";  
     
	 //Render method
	 this.render = function (){
	   //Ciclo di renderizzazione dei campi della relazione
	   for(i=0;i<this.relFields.length;i++){
	     this.relFields[i].render();
	   } 	
	 } 	

	 //addField method
	 this.addField = function (nameFieldFrom,nameFieldTo){
	  	
	   var relField = new RelationField(this.from.fieldByName(nameFieldFrom),this.to.fieldByName(nameFieldTo));
	   
	   relField.Graph = this.Graph;
       relField.hideRelationFieldName	= this.hideRelationFieldName;
	   
	   //Add field to collection
	   this.relFields[this.relFields.length]=relField;
	   
	   return this;	
     }
   }

   //EntityField Class 
   function EntityField(name,type,descr) {
	 this.name=name;
	 this.type=type;
	 this.descr=descr;
 
     //Proprietà grafiche
	 this.Graph = null;
	 this.x = 0;
	 this.y = 0;
	 this. width = 0;
	 this.height =0;
	 this.group = null;
     this.r = null;
     this.font = "Tahoma";
     this.fontSize = "10";

     //Positioning method
     this.position = function (idxField,parent_x,parent_y){
	   //Pre-impostazione proprietà grafiche per la visualizzazione dei fileds in colonna 
       this.x =parent_x;
       this.y =parent_y + (this.height * (idxField+1));
     }

	 this.setWidth = function (Width){
       this.r.attr({ "width" : + Width});
     }

	 //Render method
	 this.render = function (group){
	 	
   	   this.group = group;
   	   
   	   var r = this.Graph.rect(this.x,this.y,this.width,this.height)
                  	    .attr({ "fill" : "white" 
	                           }
	                          );
	   
	   this.r = r;

       this.r.descr = this.descr;//Extended property
       this.r.statusBar = this.ParentSchema.statusBar;//Referenza alla statusBar
       
	   //Over
	   r.hover(function () {
		 //r.attr("fill", "green");
		 r.statusBar.attr({ "text" : r.descr  });
	   }, function () {
		 //r.attr("fill", "red");
		 r.statusBar.attr({ "text" : ""  });
	   }); 
	   
	   this.group.push(this.r);
	   
	   var t = this.Graph.text(this.x + 2 , this.y , this.name + " " + this.type)
	                     .attr({ "font-family" : this.font 
	                            ,"font-size"   : this.fontSize
	                            ,"text-anchor"   : "start"
	                           }
	                          ); 
	   //Redefine Y of text based on is HEIGHT
	   t.attr({ "y": this.y + + (r.getBBox().height/2)  });
	   
       //Redefine WIDTH of rect base on text WIDTH
       r.attr({ "width" : + t.getBBox().width + 1 + 1 + 1});
       
       group.push(t);

       //Info object
       //TODO Insert circloe icon Information Rapahel free icon 
       
   	   /*var pi = this.Graph.circle(this.x+ this.width -((this.width/10)*1),this.y+((this.width/10)*1) ,((this.width/15)*1))
						 .attr({ "fill" : "blue"
						        ,"stroke": "black",
	                           }
	                          );       
       
       pi.descr = this.descr;
       pi.node.onclick = function () { 
       	  alert(pi.descr);
       }; 
       
	   pi.hover(function () {
		 pi.attr("fill", "green");
	   }, function () {
		 pi.attr("fill", "red");
	   });               

       group.push(pi);*/

	 } 	

	 //X center
	 this.centerX = function (){
	   var BBox = this.r.getBBox();
	   return BBox.x + (BBox.width / 2);	
	 }
	 //Y center
	 this.centerY = function (){
	   var BBox = this.r.getBBox();
	   return BBox.y + (BBox.height / 2);	
	 }
	 
	 //Handler EST X
	 this.handlerEstX = function (){
	   var BBox = this.r.getBBox();
	   return BBox.x + BBox.width;	   
	 }
	 //Handler EST Y
	 this.handlerEstY = function (){
	   return this.centerY();	
	 }

	 //Handler OVEST X
	 this.handlerOvestX = function (){
	   var BBox = this.r.getBBox();
	   return BBox.x;	
	 }
	 //Handler OVEST Y
	 this.handlerOvestY = function (){
	   return this.centerY();	
	 }

   }
   
   //Entity class
   function Entity(schema,name,descr) {
	 this.schema = schema;
	 this.name=name;
	 this.descr=descr;
	 this.fields = new Array();
	 
	 this.box = null;
	 this.r = null;  
	 
	 /*Default grapich property of entity */
	 this.Graph = null;
	 
	 this.x = 0; //TODO Valutare eliminazione di questi attributi in favore della getBBox del relativo rettangolo 
	 this.y = 0;
	 this. width = 150; //Larghezza predefinita della entità
	 this.height =30;//Altezza predefinita della entità TODO dovrebbe essere definita in funzione dell'altezza del testo 
	 	 
     this.font = "Tahoma";
     this.fontSize = "10";

     //Search method field by name 
     this.fieldByName = function (name){
	   for(var i=0;i<this.fields.length;i++){
	   	 if(this.fields[i].name == name ) return this.fields[i];
	   }  
	   return NULL;
     }	
     
	 //addField method
	 this.addField = function (name,type,descr){
	   var field = new EntityField(name,type,descr);
	   
	   //Set field dimension
       field.width  =150;
       field.height =30;
       field.Graph = this.Graph;

       field.font = this.font;
       field.fontSize = this.fontSize;
       
       //Position of filed based on is progresssive 
       field.position(this.fields.length,this.x,this.y);               
       
       field.ParentSchema = this.ParentSchema;
       			   			   
	   //Add field to collection
	   this.fields[this.fields.length]=field;
	   
	   return field;	
     }		 	

	 this.getMaxWidth = function (){
	   var maxWidth =0;
	   
	   for(var i=0;i<this.fields.length;i++){
	   	 var width =this.fields[i].r.getBBox().width;
	   	 if(width>maxWidth) maxWidth = width;	   	 
       } 
       
       return maxWidth;
     }

	 			 
	 //Move method
	 this.mymove = function (x,y){
       mymoveBox(x,y,this.box);
     }
    
	 //Render method
	 this.render = function (){

   	   this.box = this.Graph.set();
   	   this.box.ParentSchema = this.ParentSchema; //!!Referenza all'intero Schema per poter attraversare le relazioni 
   	   this.box.tabName = this.name; //!!Entity name

   	   var r = this.Graph.rect(this.x,this.y,this.width,this.height)
						 .attr({ "fill" : "grey" 
	                           }
	                          );     
       this.r = r;
       
       this.r.descr = this.descr;//Extended property
       this.r.statusBar = this.ParentSchema.statusBar;//StatusBar reference
       
	   //Over
	   r.hover(function () {
		 //r.attr("fill", "green");
		 r.statusBar.attr({ "text" : r.descr  });
	   }, function () {
		 //r.attr("fill", "red");
		 r.statusBar.attr({ "text" : ""  });
	   }); 
	                           
       this.box.push(this.r);           	   
   	   
   	   
	   var t = this.Graph.text(this.x + 2 ,this.y ,this.schema + "." + this.name)
	                     .attr({ "font-family" : this.font 
	                            ,"font-size"   : this.fontSize
	                            ,"text-anchor"   : "start"
	                            ,"stroke" :"black"
	                            ,"stroke-width" : 0
	                           }
	                          ); 

	   //Ridefinizione della posizione Y del testo in base alla sua altezza
	   t.attr({ "y": this.y + (this.r.getBBox().height/2)});  

       this.box.push(t);


       //************************	   

       //Rendering entity fields
	   for(var i=0;i<this.fields.length;i++){
	   	 this.fields[i].render(this.box);
	   }  

       //Normalize width
       var maxWidth = this.getMaxWidth();
	   for(var i=0;i<this.fields.length;i++){
	   	 this.fields[i].setWidth(maxWidth);
	   }  

       //Normalize width of Entity
       this.r.attr({ "width" : + maxWidth});


       //*********************************
       //Oggetto Info
       //Inserire icona tonda con I 
       
   	   /*var ri = this.Graph.rect(this.x+ this.width -((this.width/10)*2),this.y,((this.width/10)*2),this.height)
						 .attr({ "fill" : "red" 
	                           }
	                          );      
       */
      
       /*var BBox = r.getBBox();
      
       var ri = this.Graph.rect(BBox.x+BBox.width,BBox.y,20,20); //TODO
       //ri.descr = this.descr;
       
       /*ri.node.onclick = function () { 
       	  alert(ri.descr);
       }; 
       
       //this.ToolTip = new ToolTip(this,Graph,BBox.x,BBox.y,this.descr);
       
	   ri.hover(function () {
		 ri.attr("fill", "green");
	   }, function () {
		 ri.attr("fill", "red");
	   }); */               
       
       //this.box.push(ri);
      
       //*********************************
       
           	   
	   //Set entity box as draggabole object
	   this.box.draggable();
	   
	 } 	
   }        
